using System;
using System.Collections.Generic;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Data.SqlClient;
using System.Threading;


using ImageFast;
using QTOControlLib;
using QTOLibrary;
using DoublePixel;
using ICSharpCode.SharpZipLib.Zip;


namespace AssetCapture
{
    public partial class AutoIngest : Form
    {
        //string m_ConnectionString = @"Data Source=SQL01;Initial Catalog=RawTest02;Persist Security Info=True;User ID=sa ; Password=sa";
        string m_ConnectionString = @"Data Source=SQL01;Initial Catalog=SuperSign;Persist Security Info=True;User ID=sa ; Password=sa";
        //string m_ConnectionString = @"Data Source=STDEVELOPMENT\SHOWANDTELL;Initial Catalog=SuperSign;Persist Security Info=True;User ID=sa ; Password=magnolia2";
        //string m_ConnectionString = @"Data Source=SQL01;Initial Catalog=SuperSignAssetCapture;Persist Security Info=True;User ID=sa ; Password=sa";
        FrameCalculate m_FrameCal = new FrameCalculate();
        ImageIngestion m_ImageOb = new ImageIngestion();
        ArrayList deleteTmp = new ArrayList();
        PipeClient pClient;
        int m_Left_STW, m_Left_STH, m_Left_LW, m_Left_LH;
        int m_Right_STW, m_Right_STH, m_Right_LW, m_Right_LH;
        int m_RectHight, m_RectWidth, m_RectHStart, m_RectWStart;
        int m_OutputFormat;
        bool m_Interlacing;
        bool m_SameSize;
        bool m_pause;
        bool m_IngestedFromFolder = false;
        bool m_MitsuDoubleFrame = false;
        int m_Display;
        int m_Quality;
        int m_FrameHight, m_FrameWidth;
        int m_player;
        int m_offset = 0;
        string m_Error;
        string m_LogCommand;
        string m_GlobalIngestFolder;

        /// <summary>
        /// Main Function for Auto Ingestion , it will loop into the FTP folder that defined in the SQL table to ingest and create media.
        /// All file must have proper name assigned , otherwise will be throw into the "Fail" Folder, 
        /// The accepting format are .avi, .mov and .zip file that contained image squences.
        /// </summary>
        public AutoIngest()
        {
            //try
            //{
                InitializeComponent();

                m_ImageOb.EncoderInit();

                pClient = new PipeClient();

                ClientConnect();

                bool sent = false;

                while (true)
                {
                    ShowStopping(false);

                    string command = "select value from GlobalConfig where Property = 'FTPBatchIngestPath'";
                    string ingestFolder = getDataObject(command).ToString();

                    //ingestFolder = @"\\Asset01\SharedDocs\BatchTest";
                    m_GlobalIngestFolder = ingestFolder + "\\Success";

                    if (!Directory.Exists(m_GlobalIngestFolder))
                        Directory.CreateDirectory(m_GlobalIngestFolder);

                    checkLogin();

                    if (!sent)
                        pClient.SendMessage("Auto Ingestion Start Up");

                    sent = true;

                    command = "sproc_ATC_Sel_VideoStorePath"; //Call stored procedure for retrieving the videostoredpath from GlobalConfig Table
                    string VideoStorePath = getDataObject(command).ToString();
                    //VideoStorePath = @"\\Asset01\SharedDocs\MediaTest";
                    m_MitsuDoubleFrame = false;

                    StartIngest(ingestFolder, VideoStorePath);

                    Thread.Sleep(20000);
                }
            //}
            //catch (Exception err)
            //{
            //    StreamWriter errorWrite = new StreamWriter(Application.StartupPath + "\\ErrorReporting.txt", true);

            //    errorWrite.WriteLine(DateTime.UtcNow.ToString() + err);
            //    errorWrite.Close();
            //}
            //finally
            //{
            //    //System.Diagnostics.Process.Start(Application.ExecutablePath);

            //    Application.Exit();
            //}
        }

        private void ClientConnect()
        {
            if (!pClient.Connected)
            {
                pClient.PipeName = @"\\.\pipe\Asset\";
                pClient.Connect();
                Thread.Sleep(2000);
            }
        }

        /// <summary>
        /// check if the user has logged into the system or not
        /// if Yes, the autoIngest process will remain sleep until user log out the AssetCapture APP
        /// </summary>
        private void checkLogin()
        {
            string command = "select value from GlobalConfig where Property = 'AssetUserLogin'";
            bool save = false;
            m_pause = Convert.ToBoolean(getDataObject(command));

            //m_pause = false;

            while(m_pause)
            {
                if (!save)
                    pClient.SendMessage("User Login, Auto Ingestion Paused");

                CheckDate();
                Thread.Sleep(6000);
                m_pause = Convert.ToBoolean(getDataObject(command));
                save = true;
            }
            if(save)
                pClient.SendMessage("User Logout , Auto Ingestion Checks if any Media for ingestion");
        }

        /// <summary>
        /// Check the date of file been saved in the success folder 
        /// if the creation date is 5 days or more, it will be deleted.
        /// </summary>
        private void CheckDate()
        {
            DirectoryInfo dir = new DirectoryInfo(m_GlobalIngestFolder);
            FileInfo[] fInfo = dir.GetFiles();

            foreach (FileInfo fIn in fInfo)
            {
                DateTime currentTime = DateTime.Now.Date;
                DateTime createdDtate = fIn.CreationTime.Date;
                TimeSpan diff = currentTime.Subtract(createdDtate);
                if (diff.Days > 4)
                {
                    try
                    {
                        File.Delete(fIn.FullName);
                    }
                    catch (Exception err)
                    {
                    }
                }
            }
        }

        private void ReportErr(object dumpob)
        {
            pClient.SendMessage(m_Error);
            MessageBox.Show(m_Error);
        }

        /// <summary>
        /// Filter function that removed all the illegal character
        /// </summary>
        /// <param name="beforeFilter">String need to be filtered</param>
        /// <returns>the string that has been filterd</returns>
        private string NameFilter(string beforeFilter)
        {
            beforeFilter = beforeFilter.Replace("'", "");
            beforeFilter = beforeFilter.Replace("~", "");
            beforeFilter = beforeFilter.Replace("!", "");
            beforeFilter = beforeFilter.Replace("@", "");
            beforeFilter = beforeFilter.Replace("#", "");
            beforeFilter = beforeFilter.Replace("$", "");
            beforeFilter = beforeFilter.Replace("%", "");
            beforeFilter = beforeFilter.Replace("^", "");
            beforeFilter = beforeFilter.Replace("&", "");
            beforeFilter = beforeFilter.Replace("*", "");
            beforeFilter = beforeFilter.Replace("(", "");
            beforeFilter = beforeFilter.Replace(")", "");
            beforeFilter = beforeFilter.Replace("-", "");
            beforeFilter = beforeFilter.Replace("+", "");
            beforeFilter = beforeFilter.Replace("{", "");
            beforeFilter = beforeFilter.Replace("}", "");

            return beforeFilter;
        }

        /// <summary>
        /// Extrac the file name for programe to ingest the file
        /// </summary>
        /// <param name="folder"></param>
        /// <param name="batchName"></param>
        /// <param name="OutputFormat"></param>
        /// <param name="imageSet"></param>
        /// <param name="folderName"></param>
        /// <param name="fileByte"></param>
        /// <returns></returns>
        private bool ExtractFileName(bool folder, string batchName, out string OutputFormat, out string imageSet, out string folderName, out Double fileByte)
        {
            batchName = NameFilter(batchName);

            string[] fileDetail;

            if(folder)
                fileDetail = batchName.Split('_');
            else
                fileDetail = batchName.Remove(batchName.Length - 4).Split('_');
            try
            {         
                fileByte = Convert.ToDouble(fileDetail[fileDetail.Length - 1].Replace(",", ""));
                OutputFormat = fileDetail[fileDetail.Length - 2];
                imageSet = fileDetail[fileDetail.Length - 3];
                folderName = batchName.Remove(batchName.IndexOf(imageSet) - 1);

                if (folderName.Length > 40)
                    folderName = folderName.Remove(40);

                return true;
            }
            catch (Exception err)
            {
                OutputFormat = "";
                imageSet = "";
                folderName = "";
                fileByte = 0;

                m_Error = "Problem with parsing file Name \n" + err;
                ThreadPool.QueueUserWorkItem(new WaitCallback(ReportErr));
                return false;
            }           
        }

        /// <summary>
        /// The main function that start autoIngest 
        /// </summary>
        /// <param name="FTPFolder"></param>
        /// <param name="VideoStoredPath"></param>
        private void StartIngest(string FTPFolder, string VideoStoredPath)
        {
            string OutputFormat;
            string imageSet;
            string folderName;
            string idleCheckCommand;
            Double fileByte;
            bool continueProcess;
            bool success;

            m_offset = 0;

            if (File.Exists(FTPFolder + "\\Thumbs.db"))
                File.Delete(FTPFolder + "\\Thumbs.db");

            DirectoryInfo dir = new DirectoryInfo(FTPFolder);
            DirectoryInfo[] dirInfoArray = dir.GetDirectories();
            FileInfo[] fileInfoArray = dir.GetFiles();

            string failPath = FTPFolder + "\\Fail";

            if (!Directory.Exists(failPath))
                Directory.CreateDirectory(failPath);


            foreach (DirectoryInfo dirInfo in dirInfoArray)
            {
                if (dirInfo.Name != "Fail" && dirInfo.Name != "Success")
                {
                    idleCheckCommand = "Update Globalconfig set Value = 'false' where Property = 'FTPBatchIngestIdle'";
                    UpdateDataBase(idleCheckCommand);
                    
                    continueProcess = ExtractFileName(true, dirInfo.Name, out OutputFormat, out imageSet, out folderName, out fileByte);
                    pClient.SendMessage("Extracting Folder Name : " + dirInfo.Name + ", OutputFormat : " + OutputFormat + ", ImageSet :" + imageSet);

                    if (!continueProcess)
                    {
                        LogActivity();
                        try
                        {
                            pClient.SendMessage("Folder Parameter is incorrect, Folder will be moved to the fail Folder");
                            Directory.Move(dirInfo.FullName, failPath + "\\" + dirInfo.Name);
                        }
                        catch (Exception err)
                        {
                            //MessageBox.Show("Error on Extracting File Name Suffix \n" + err);
                            pClient.SendMessage("Error Occured when moving the Folder " + dirInfo.Name + " into the Fail Folder");
                        }
                        return;
                    }

                    bool ImageSet;
                    if (imageSet == "VID")
                        ImageSet = false;
                    else
                        ImageSet = true;

                    m_IngestedFromFolder = true;

                    pClient.SendMessage("Start Ingesting the Folder : " + folderName);
                    success = DealFolder(VideoStoredPath, dirInfo.FullName, OutputFormat, ImageSet, folderName);

                    if (success)
                    {
                        pClient.SendMessage("Ingesting the Folder : " + dirInfo.Name + " Successful");

                        try
                        {
                            Directory.Delete(dirInfo.FullName, true);
                        }
                        catch (Exception err)
                        {
                            deleteTmp.Add(dirInfo.FullName);
                        }
                    }
                    else
                    {
                        pClient.SendMessage("Ingesting the Folder : " + dirInfo.Name + " is Failed");
                        LogActivity();
                        try
                        {
                           Directory.Move(dirInfo.FullName, failPath + "\\" + dirInfo.Name);
                        }
                        catch (Exception err)
                        {
                            //MessageBox.Show("Error on Ingesting Content , Check the Fail Folder \n" + err);
                        }
                    }
                }
            }

            foreach (FileInfo fInfo in fileInfoArray)
            {
                bool escape = false;

                if (fInfo.Name != "Thumbs.db")
                {
                    idleCheckCommand = "Update Globalconfig set Value = 'false' where Property = 'FTPBatchIngestIdle'";
                    UpdateDataBase(idleCheckCommand);

                    continueProcess = ExtractFileName(false, fInfo.Name, out OutputFormat, out imageSet, out folderName, out fileByte);
                    pClient.SendMessage("Extracting File Name : " + fInfo.Name + ", OutputFormat : " + OutputFormat + ", ImageSet :" + imageSet);

                    if (!continueProcess)
                    {
                        pClient.SendMessage("File Parameter is incorrect, File will be moved to the fail Folder");
                        LogActivity();
                       
                        try
                        {
                            pClient.SendMessage("File will be moved to the fail Folder");
                            File.Move(fInfo.FullName, failPath + "\\" + fInfo.Name);
                        }
                        catch (Exception err)
                        {
                            pClient.SendMessage("Error Occured when moving the Folder " + fInfo.Name + " into the Fail Folder " + err);
                        }
                        return;
                    }

                    if (fileByte != 1)
                    {
                        if (fInfo.Length != fileByte)
                        {
                            pClient.SendMessage("File Byte Size incorrect, the File has been skipped");
                            escape = true;
                            //try
                            //{
                            //    escape = true;
                            //    File.Move(fInfo.FullName, failPath + "\\" + fInfo.Name);
                            //}
                            //catch (Exception err)
                            //{
                            //}
                        }
                    }

                    if (!escape)
                    {
                        if (fInfo.Extension.ToLower() == ".zip")
                        {
                            FastZip fz = new FastZip();
                            fz.ExtractZip(fInfo.FullName, fInfo.DirectoryName + "\\" +fInfo.Name.Replace(fInfo.Extension,""), "");
                            pClient.SendMessage("Zip File : " + fInfo.FullName + " Extraction Complete");
                            string successPath = FTPFolder + "\\Success";

                            if (!Directory.Exists(successPath))
                                Directory.CreateDirectory(successPath);

                            try
                            {
                                pClient.SendMessage("Trying to move the Zip file into Success Folder");
                                File.Move(fInfo.FullName, successPath + "\\" + fInfo.Name);
                                pClient.SendMessage("Move the Zip file into Success Folder sucessfully");
                            }
                            catch (Exception err)
                            {
                            }
                        }
                        else if (fInfo.Extension.ToLower() == ".avi" || fInfo.Extension.ToLower() == ".mov")
                        {
                            m_IngestedFromFolder = false;

                            bool ImageSet;
                            if (imageSet == "VID")
                                ImageSet = false;
                            else
                                ImageSet = true;

                            pClient.SendMessage("Start to Extract the Image From Movie File");
                            success = DealVideo(VideoStoredPath, fInfo.FullName, OutputFormat, ImageSet, folderName);
                            axQTControl1.URL = "";

                            if (success)
                                File.Delete(fInfo.FullName);
                            else
                            {
                                LogActivity();
                                try
                                {
                                    File.Move(fInfo.FullName, failPath + "\\" + fInfo.Name);
                                }
                                catch (Exception err)
                                {
                                }
                           } 
                        }
                    }
                }

                escape = false;
            }

            idleCheckCommand = "Update Globalconfig set Value = 'true' where Property = 'FTPBatchIngestIdle'";
            UpdateDataBase(idleCheckCommand);
        }

        /// <summary>
        /// Function that log activity
        /// </summary>
        private void LogActivity()
        {
            m_LogCommand = "sproc_LogActivity @DateTime ='" + DateTime.Now.ToString() + "', @ActivityID=15000, @ObjectID=0, @Level = 13, @Description='Batch Ingestion Fail', @UserID = 0";
            UpdateDataBase(m_LogCommand);
        }

        /// <summary>
        /// Update the Database , no return object
        /// </summary>
        /// <param name="command"></param>
        public void UpdateDataBase(string command)
        {
            SqlConnection con = new SqlConnection(m_ConnectionString);
            SqlCommand cmd = new SqlCommand(command, con);

            // Try to open the database and execute the update.
            try
            {
                con.Open();
                cmd.ExecuteNonQuery();
            }
            catch (Exception err)
            {
                //displayError("Update SQL Connection Fail \n" + err);
            }

            finally
            {
                con.Close();
            }

        }

        /// <summary>
        /// Function that call when ingest from the folder
        /// </summary>
        /// <param name="savingPath"></param>
        /// <param name="folderpath"></param>
        /// <param name="outputFormat"></param>
        /// <param name="imageSet"></param>
        /// <param name="folderName"></param>
        /// <returns></returns>
        private bool DealFolder(string savingPath, string folderpath, string outputFormat, bool imageSet, string folderName)
        {
            m_Quality = 100;

            char channel;
            int player;
            bool Ribbon;
            bool sucess;

            GetAttribute(outputFormat, out channel, out player, out Ribbon);

            string[] savingFolder = GetFrameSet(channel, player, savingPath,  folderName, outputFormat);//, player, size, testFrame.Width, testFrame.Height);

            if (File.Exists(folderpath + "\\Thumbs.db"))
                File.Delete(folderpath + "\\Thumbs.db");

            DirectoryInfo dir = new DirectoryInfo(folderpath);
            int totalFrame = dir.GetFiles().Length;

            sucess = ImageProcess(folderpath, savingFolder, player, false);

            if (m_Interlacing || m_MitsuDoubleFrame)
                totalFrame = totalFrame * 2;

            if (!sucess)
            {
                deleteTmp.Add(folderpath);
                deleteTmp.Add(savingFolder[0]);

                if (player == 0)
                    deleteTmp.Add(savingFolder[1]);

                return sucess;
            }

            if (savingFolder[1] != null)
            {
                CreateMedia(savingFolder[0], 1, 2, folderpath, imageSet, totalFrame);
                CreateMedia(savingFolder[1], 2, 2, folderpath, imageSet, totalFrame);
            }
            else
                CreateMedia(savingFolder[0], 1, 1, folderpath, imageSet, totalFrame);

            return sucess;
        }

        private void GetAttribute(string outputFormat, out char channel, out int player, out bool Ribbon)
        {
            m_Quality = 100;
            Ribbon = false;

            if (outputFormat.Length == 2)
            {
                channel = outputFormat[0];
                player = 1;

                if (channel == 'T')
                    player = 2;

                m_OutputFormat = Convert.ToInt32(outputFormat[1].ToString());
            }
            else
            {
                channel = 'R';
                if (outputFormat[1] == 'F')
                    player = 0;
                else
                    player = 1;
                m_OutputFormat = Convert.ToInt32(outputFormat[2].ToString());
            }

            if (channel != 'M')
                Ribbon = true;
        }

        /// <summary>
        /// Function that call when ingest from the video
        /// </summary>
        /// <param name="savingPath"></param>
        /// <param name="filePath"></param>
        /// <param name="outputFormat"></param>
        /// <param name="imageSet"></param>
        /// <param name="folderName"></param>
        /// <returns></returns>
        private bool DealVideo(string savingPath, string filePath, string outputFormat, bool imageSet, string folderName)
        {
            checkLogin();

            char channel;
            int player;
            bool Ribbon;
            bool status;
            int tmpCounter = 1;

            GetAttribute(outputFormat, out channel, out player, out Ribbon);

            string tempFolder = savingPath + "\\TempFolder\\" + folderName;
            string sqlCommand = "Select Value from Globalconfig where Property = 'AudioStorePath'";
            string audioName = getDataObject(sqlCommand).ToString() + "\\" + folderName + ".wav";

            while (Directory.Exists(tempFolder))
                tempFolder = tempFolder + "_" + tmpCounter++;

            Directory.CreateDirectory(tempFolder);

            ExtractImage(Ribbon, filePath, tempFolder, audioName);
            pClient.SendMessage("Extracting the Image From Movie File Successfully");
            checkLogin();

            DirectoryInfo dir= null;
            int totalFrame = 0; 

            if (File.Exists(tempFolder + "\\Thumbs.db"))
                File.Delete(tempFolder + "\\Thumbs.db");

            dir = new DirectoryInfo(tempFolder);
            totalFrame= dir.GetFiles().Length;
            

            string[] savingFolder = GetFrameSet(channel, player, savingPath, folderName, outputFormat);//, player, size, testFrame.Width, testFrame.Height);

            string CheckName = folderName.Substring(0, 3);
            bool SYNC = false;

            if (CheckName == "SYN")
                SYNC = true;
 
            status = ImageProcess(tempFolder, savingFolder, player, SYNC);


            if (!status)
            {
                deleteTmp.Add(tempFolder);
                deleteTmp.Add(savingFolder[0]);

                if (player == 0)
                    deleteTmp.Add(savingFolder[1]);
                
                return status;
            }

            if (File.Exists(savingFolder + "\\Thumbs.db"))
                File.Delete(savingFolder + "\\Thumbs.db");

            if(m_MitsuDoubleFrame || m_Interlacing)
            {
                totalFrame = totalFrame * 2;
            }

            if (savingFolder[1] != null)
            {
                CreateMedia(savingFolder[0], 1, 2, filePath, imageSet, totalFrame);
                CreateMedia(savingFolder[1], 2, 2, filePath, imageSet, totalFrame);
            }
            else
                CreateMedia(savingFolder[0], 1, 1, filePath, imageSet, totalFrame);

            return status;
        }

        /// <summary>
        /// Function that are been used to create the media after ingestion 
        /// </summary>
        /// <param name="sourceFolder"></param>
        /// <param name="sliceIndex"></param>
        /// <param name="sliceCount"></param>
        /// <param name="ingestedPath"></param>
        /// <param name="imageSet"></param>
        /// <param name="fileCount"></param>
        /// <returns></returns>
        private int CreateMedia(string sourceFolder, int sliceIndex, int sliceCount, string ingestedPath, bool imageSet, int fileCount)
        {
            ingestedPath = NameFilter(ingestedPath);

            int mediaID;
            int userID = 0;

            string[] foldernames = sourceFolder.Split('\\');
            string fName = foldernames[foldernames.Length - 1];
            pClient.SendMessage("Creating Media: "+ fName);
            string command = "sproc_ATC_Insert_Media @IsFrameSequence = 'true', @SourcePath ='" + fName + "', @FileCount = " + fileCount + ", @IsImageSet = '" + imageSet.ToString() + "' , @IngestedFromPath ='" + ingestedPath + "', @Height = " + m_FrameHight + ", @Width =" + m_FrameWidth + ", @SliceIndex =" + sliceIndex.ToString() + ", @SliceCount=" + sliceCount.ToString() + ", @UserID=" + userID;
            mediaID = Convert.ToInt32(getDataObject(command));
            pClient.SendMessage("Media Created, Media ID : " + mediaID);
            return mediaID;
        }

        /// <summary>
        /// Set the parameter for the saving path
        /// </summary>
        /// <param name="channel"></param>
        /// <param name="player"></param>
        /// <param name="savingPath"></param>
        /// <param name="folderName"></param>
        /// <param name="outPutFormat"></param>
        /// <returns></returns>
        private string[] GetFrameSet(char channel, int player , string savingPath,  string folderName, string outPutFormat)//, int player, int outputSize, int oImageWidth, int oImageHight)
        {
            string[] savingFolder = new string[2];
            int count = 1;

            if (channel == 'M')
            {
                m_FrameWidth = 1280;
                m_FrameHight = 720;

                m_Display = 1;
                string savingName = savingPath + "\\M_"+ folderName + "_" + outPutFormat + "_1_" + count;

                while (Directory.Exists(savingName))
                {
                    count++;
                    savingName = savingPath + "\\M_" + folderName + "_" + outPutFormat + "_1_" + count;
                }
                Directory.CreateDirectory(savingName);
                savingFolder[0] = savingName;
            }
            else if (channel == 'R')
            {
                m_FrameHight = 1080;
                m_FrameWidth = 2048;

                m_Display = 2;

                string savingName = savingPath + "\\R_" + folderName + "_" + outPutFormat + "_1_" + count;

                while (Directory.Exists(savingName))
                {
                    count++;
                    savingName = savingPath + "\\R_" + folderName + "_" + outPutFormat + "_1_" + count;
                }
                Directory.CreateDirectory(savingName);
                savingFolder[0] = savingName;

                if (player == 0)
                {
                    savingName = savingPath + "\\R_" + folderName + "_" + outPutFormat + "_2_" + count;

                    while (Directory.Exists(savingName))
                    {
                        count++;
                        savingName = savingPath + "\\R_" + folderName + "_" + outPutFormat + "_2_" + count;
                    }
                    Directory.CreateDirectory(savingName);
                    savingFolder[1] = savingName;
                }
            }
            else
            {
                m_Display = 3;
                m_FrameHight = 1080;
                m_FrameWidth = 2048;
                string savingName = savingPath + "\\T_" + folderName + "_" + outPutFormat + "_1_" + count;

                while (Directory.Exists(savingName))
                {
                    count++;
                    savingName = savingPath + "\\T_" + folderName + "_" + outPutFormat + "_1_" + count;
                }
                Directory.CreateDirectory(savingName);
                savingFolder[0] = savingName;
               // m_FraeCa.GetTickerFrame((double)oImageWidth, (double)oImageHight, out m_RectHight);
            }

            return savingFolder;
        }

        /// <summary>
        /// Extract frames from the given Video Path, will Take .avi and .mov 
        /// </summary>
        /// <param name="MoviePathName">Movie Path </param>
        /// <param name="targetPathName">Saving Path</param>
        /// <param name="giveTotalFrame">Call Back Function to give the total Frame will be extracted</param>
        /// <param name="trace">Call Back Error Tracing </param>
        private void ExtractImage(bool Ribbons, string MoviePathName, string targetPathName , string audioName)
        {
            axQTControl1.URL = MoviePathName;
            QTMovie theMovie = axQTControl1.Movie;
            QTQuickTime qt = axQTControl1.QuickTime;
            int totalFrame;
            
            if (qt.Exporters.Count == 0) qt.Exporters.Add();
            QTExporter ex = qt.Exporters[1];

            ex.TypeName = "Image Sequence";
            ex.SetDataSource(axQTControl1.Movie);

            FileInfo fInfo = new FileInfo(MoviePathName);

            //Load the XML Setting
            CFObject cf = new CFObject();
            //cf.XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>Date</key>\n\t<string>Mon Jul 30 11:16:42 2007\n</string>\n\t<key>Format</key>\n\t<string>grex</string>\n\t<key>Name</key>\n\t<string>Image Sequence</string>\n\t<key>SettingsData</key>\n\t<data>\n\tAAAAAAAAAAAAAAAAAAAAbXNlYW4AAAABAAAAAwAAAAAAAAAsdGltZQAAAAEAAAABAAAA\n\tAAAAABhmcHMgAAAAAQAAAAAAAAAAAAAAAAAAABhmdHlwAAAAAQAAAAAAAAAASlBFRwAA\n\tABUiICI/AAAAAQAAAAAAAAAAAQ==\n\t</data>\n\t<key>Type</key>\n\t<string>Movie</string>\n</dict>\n</plist>\n";

            if (Ribbons)
            {
                cf.XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>Date</key>\n\t<string>Mon Oct 15 12:11:23 2007\n</string>\n\t<key>Format</key>\n\t<string>grex</string>\n\t<key>Name</key>\n\t<string>Image Sequence</string>\n\t<key>SettingsData</key>\n\t<data>\n\tAAAAAAAAAAAAAAAAAAAAbXNlYW4AAAABAAAAAwAAAAAAAAAsdGltZQAAAAEAAAABAAAA\n\tAAAAABhmcHMgAAAAAQAAAAAAAAAAAB4AAAAAABhmdHlwAAAAAQAAAAAAAAAAQk1QZgAA\n\tABUiICI/AAAAAQAAAAAAAAAAAA==\n\t</data>\n\t<key>Type</key>\n\t<string>Movie</string>\n</dict>\n</plist>\n";
                m_MitsuDoubleFrame = false;
            }
            else
            {
                cf.XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>Date</key>\n\t<string>Fri Oct 12 14:20:03 2007\n</string>\n\t<key>Format</key>\n\t<string>grex</string>\n\t<key>Name</key>\n\t<string>Image Sequence</string>\n\t<key>SettingsData</key>\n\t<data>\n\tAAAAAAAAAAAAAAAAAAAAbXNlYW4AAAABAAAAAwAAAAAAAAAsdGltZQAAAAEAAAABAAAA\n\tAAAAABhmcHMgAAAAAQAAAAAAAAAAAAAAAAAAABhmdHlwAAAAAQAAAAAAAAAAQk1QZgAA\n\tABUiICI/AAAAAQAAAAAAAAAAAQ==\n\t</data>\n\t<key>Type</key>\n\t<string>Movie</string>\n</dict>\n</plist>\n";

                if (theMovie.StaticFrameRate < 31)
                    m_MitsuDoubleFrame = true;
                
                if (theMovie.StaticFrameRate == 30 || theMovie.StaticFrameRate == 60 || fInfo.Extension.ToLower() == ".avi")
                    totalFrame = (int)(theMovie.EndTime * theMovie.StaticFrameRate / 600);
                else
                {
                    totalFrame = (int)(theMovie.EndTime / 100);
                }

                if (totalFrame > 65534)
                {
                    cf.XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>Date</key>\n\t<string>Thu Feb 21 10:08:41 2008\n</string>\n\t<key>Format</key>\n\t<string>grex</string>\n\t<key>Name</key>\n\t<string>Image Sequence</string>\n\t<key>SettingsData</key>\n\t<data>\n\tAAAAAAAAAAAAAAAAAAAAo3NlYW4AAAABAAAABAAAAAAAAAAsdGltZQAAAAEAAAABAAAA\n\tAAAAABhmcHMgAAAAAQAAAAAAAAAAAB4AAAAAABhmdHlwAAAAAQAAAAAAAAAAQk1QZgAA\n\tADZ2aWRlAAAAAQAAAAEAAAAAAAAAInNwdGwAAAABAAAAAAAAAABXUkxFAAAAAAAAAAAE\n\tAAAAABUiICI/AAAAAQAAAAAAAAAAAA==\n\t</data>\n\t<key>Type</key>\n\t<string>Movie</string>\n</dict>\n</plist>\n";
                    m_MitsuDoubleFrame = true;
                }
            }
            ex.Settings = cf;

            //Export Movie

            ex.DestinationFileName = targetPathName + "\\" + "Temp";
            ex.ShowProgressDialog = false;
            try
            {
                //Start Exporting 
                bool stopping = true;
                ShowStopping(stopping);
                ex.BeginExport();
                stopping = false;
                ShowStopping(stopping);
            }
            catch (Exception err)
            {
                // catch any exception
                string errMsg = "Unable To Extract the Movie , Please Check if it is QuickTime Playable Video \n\n" + err.ToString();
                trace(errMsg);
            }

            //if (qt.Exporters.Count == 1) qt.Exporters.Add();
            //QTExporter ex2 = qt.Exporters[2];

            //ex2.TypeName = "Wave";
            //ex2.SetDataSource(axQTControl1.Movie);
            //cf.XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>Date</key>\n\t<string>Mon Sep 10 11:37:13 2007\n</string>\n\t<key>Format</key>\n\t<string>WAVE</string>\n\t<key>Name</key>\n\t<string>Wave</string>\n\t<key>SettingsData</key>\n\t<data>\n\tAAAAAAAAAAAAAAAAAAABbXNlYW4AAAABAAAAAQAAAAAAAAFZc291bgAAAAEAAAAGAAAA\n\tAAAAAM1hdWRpAAAAAQAAAAUAAAAAAAAAPG9zYmQAAAABAAAAAAAAAABA53AAAAAAAGxw\n\tY20AAAAMAAAABAAAAAEAAAAEAAAAAgAAABAAAAAAAAAANGNsYXkAAAABAAAAAAAAAAAA\n\tZQACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABVyZWNvAAAAAQAAAAAAAAAA\n\tAAAAABhxbHR5AAAAAQAAAAAAAAAAAAAAQAAAABx2ZXJzAAAAAQAAAAAAAAAAAAMAFQAB\n\tAAAAAAAYc3NjdAAAAAEAAAAAAAAAAHNvd3QAAAAYc3NydAAAAAEAAAAAAAAAALuAAAAA\n\tAAAWc3NzcwAAAAEAAAAAAAAAAAAQAAAAFnNzY2MAAAABAAAAAAAAAAAAAgAAABx2ZXJz\n\tAAAAAQAAAAAAAAAAAAMAFAABAAA=\n\t</data>\n\t<key>Type</key>\n\t<string>Movie</string>\n</dict>\n</plist>\n";
            //ex2.Settings = cf;
            //ex2.DestinationFileName = audioName;
            //ex2.ShowProgressDialog = false;

            //try
            //{
            //    //Start Exporting 
            //    ex2.BeginExport();
            //    ex2.CancelExport();
            //    axQTControl1.Movie.Disconnect();
            //}
            //catch (Exception err)
            //{
            //    // catch any exception
            //    string errMsg = "Unable To Extract the Audio , Please Check if thereis a Audio in the Movie \n\n" + err.ToString();
            //    trace(errMsg);
            //}
        }

        /// <summary>
        /// Set the offset value to indicate the process of Ingestion 
        /// </summary>
        /// <param name="stopping"></param>
        private void ShowStopping(bool stopping)
        {
            string sqlCommand = "Update Globalconfig set Value='"+ stopping + "' where Property = 'FTPBatchStopping'";
            UpdateDataBase(sqlCommand);
        }

        /// <summary>
        /// Show the Error Message
        /// </summary>
        /// <param name="errMsg"></param>
        private void trace(string errMsg)
        {
            pClient.SendMessage(errMsg);
        }

        /// <summary>
        /// Get the SQL command and return single object item using DataReader to speed up the communication
        /// </summary>
        /// <param name="selectSQL"></param>
        /// <returns></returns>
        public object getDataObject(string selectSQL)
        {

            SqlConnection con = new SqlConnection(m_ConnectionString);
            SqlCommand cmd = new SqlCommand(selectSQL, con);
            SqlDataReader reader = null;
            object ob = new object();

            try
            {
                con.Open();
                reader = cmd.ExecuteReader();
                reader.Read();
                ob = reader[0];//Only read ONE data in the first of list
                reader.Close();

            }
            catch (Exception err)
            {
                trace("Error occur while connect to DataBase via DataReader, Check Connection : \n" + err);
            }
            finally
            {
                con.Close();
            }
            return ob;

        }

        /// <summary>
        /// Test if the video is interlaced
        /// </summary>
        /// <param name="width"></param>
        private void TestInterLace(int width)
        {
            if (width == 1920 || width == 720)
                m_Interlacing = true;
            else
                m_Interlacing = false;
        }

        /// <summary>
        /// Start to load the iamge and to process for each channel
        /// </summary>
        /// <param name="width"></param>
        /// <param name="height"></param>
        private void LoadImage(int width, int height)
        {
            if (m_Display == 1)
            {
                if (width == 1280 && height == 720)
                    m_SameSize = true;
                else
                    m_SameSize = false;

                m_FrameCal.MitsuResize(m_OutputFormat, (double)width, (double)height, out m_Left_STW, out m_Left_STH, out m_Left_LW, out m_Left_LH, out m_RectWStart, out m_RectHStart, out m_RectWidth, out m_RectHight);
            }
            else if (m_Display == 2)
            {
                if (m_player == 1)
                    m_FrameCal.RibbonResize(m_OutputFormat, (double)width, (double)height, out m_Left_STW, out m_Left_STH, out m_Left_LW, out m_Left_LH, out m_Right_STW, out m_Right_STH, out m_Right_LW, out m_Right_LH, out m_RectWStart, out m_RectHStart, out m_RectWidth, out m_RectHight);
                else
                    m_FrameCal.FullStrech(m_OutputFormat, (double)width, (double)height, out m_Left_STW, out m_Left_STH, out m_Left_LW, out m_Left_LH, out m_Right_STW, out m_Right_STH, out m_Right_LW, out m_Right_LH, out m_RectWStart, out m_RectHStart, out m_RectWidth, out m_RectHight);
            }
            else if (m_Display == 3)
            {
                m_FrameCal.GetTickerFrame(Convert.ToDouble(width), Convert.ToDouble(height), out m_RectHight);
            }
        }

        /// <summary>
        /// Extract the image from the video and give proper name for each image file
        /// </summary>
        /// <param name="tempFramePath"></param>
        /// <param name="savingFolder"></param>
        /// <param name="player"></param>
        /// <returns></returns>
        private bool ImageProcess(string tempFramePath, string[] savingFolder, int player, bool SYNC)
        {
            pClient.SendMessage("Start to process the image and saving it");
            DoublePixel.DoublePixel dbP = new DoublePixel.DoublePixel();
            DirectoryInfo dir = new DirectoryInfo(tempFramePath);
            FileInfo[] files = dir.GetFiles();
            int flagCounter = 1;
            bool processFlag = true;
            bool status;
            int threadCount;
            Image testFrame;
            int fileNextNo;
            string nextFileNoPath="";

            try
            {
                
                testFrame = ImageFast.ImageFast.FromFile(files[0].FullName);
            }
            catch (Exception err)
            {
                status = false;
                return status;
            }

            if (player == 0)
                threadCount = 3;
            else if (player == 1)
                threadCount = 4;
            else
                threadCount = 4;

            TestInterLace(testFrame.Width);

            m_player = player;

            if (!m_IngestedFromFolder)
                LoadImage(testFrame.Width, testFrame.Height);

            testFrame.Dispose();

            checkLogin();

            int Count_SkipFrame = 5;

            for(int i = 0 ; i < files.Length;i++)
            {
                //check the type of image file
                try
                {
                    string fName = files[i].Name;
                    string path = tempFramePath + "\\" + fName;

                    if (files[i].Extension.ToLower() == ".bmp" || files[i].Extension.ToLower() == ".jpg" || files[i].Extension.ToLower() == ".jpeg")
                    {
                        Image tempImage2 = ImageFast.ImageFast.FromFile(path); //Use Imagefast Library to read local file into image object

                        string suffix;
                        string imageName;

                        if (m_Display != 1 && i == 0 && SYNC)
                        {
                            int fileNo = 0;

                            GetSuffix(fileNo.ToString().Length, out suffix);
                            fName = suffix + fileNo + ".jpg";

                            imageName = savingFolder[0] + "\\" + fName;

                            ArrayList arrayMediaOB2 = new ArrayList();
                            arrayMediaOB2.Add(tempImage2);
                            arrayMediaOB2.Add(imageName);

                            if (m_Display == 2 && savingFolder[1] != null)
                                arrayMediaOB2.Add(savingFolder[1] + "\\" + fName);

                            ImageSaving(arrayMediaOB2);

                            Image repeatImg = ImageFast.ImageFast.FromFile(savingFolder[0] + "\\" + fName);

                            while (fileNo++ <= Count_SkipFrame)
                            {

                                GetSuffix(fileNo.ToString().Length, out suffix);
                                fName = suffix + fileNo + ".jpg";

                                imageName = savingFolder[0] + "\\" + fName;
                                repeatImg.Save(imageName);
                            }
                            repeatImg.Dispose();
                        }
                        else
                        {
                            //Check if interlacing is required
                            if (m_Interlacing)
                            {
                                m_MitsuDoubleFrame = false;

                                //Create new duplicated Image
                                Bitmap orignialImage = new Bitmap(tempImage2);
                                //Separated the two image

                                if (m_Display == 1)
                                {
                                    Image tempImage1 = dbP.FrameExtract((Bitmap)tempImage2, 1);

                                    //Calculate the file name
                                    int fileNo = (i - 1) * 2 + 2;
                                    GetSuffix(fileNo.ToString().Length, out suffix);
                                    imageName = suffix + fileNo + ".jpg"; //Give Proper File Name

                                    ArrayList arrayMediaOB1 = new ArrayList();
                                    arrayMediaOB1.Add(tempImage1);
                                    arrayMediaOB1.Add(savingFolder[0] + "\\" + imageName);

                                    //Start Ingesting the Image
                                    if (m_IngestedFromFolder)
                                        ImageSaving((object)arrayMediaOB1);
                                    else
                                        ThreadPool.QueueUserWorkItem(new WaitCallback(ImageSaving), (object)arrayMediaOB1);
                                    //


                                    fileNo = (i - 1) * 2 + 3;
                                    GetSuffix(fileNo.ToString().Length, out suffix);
                                    fName = suffix + fileNo + ".jpg";
                                }
                                else
                                {
                                    GetSuffix(i.ToString().Length, out suffix);
                                    fName = suffix + i + ".jpg";
                                }
                                //Set the second frame 
                                tempImage2 = dbP.FrameExtract(orignialImage, 2);
                                //processFlag = true; //Set To Create New Thread to process Image all the time
                            }
                            else
                            {
                                int fileNo;

                                if (m_MitsuDoubleFrame)
                                {
                                    fileNo = (i - 1) * 2 + 2;
                                    fileNextNo = fileNo + 1;
                                    GetSuffix(fileNextNo.ToString().Length, out suffix);
                                    nextFileNoPath = suffix + fileNextNo + ".jpg";
                                }
                                else
                                {
                                    if (m_Display != 1 && SYNC)
                                        fileNo = i + Count_SkipFrame;
                                    else
                                        fileNo = i;
                                }

                                GetSuffix(fileNo.ToString().Length, out suffix);
                                fName = suffix + fileNo + ".jpg";
                            }

                            imageName = savingFolder[0] + "\\" + fName;

                            ArrayList arrayMediaOB2 = new ArrayList();
                            arrayMediaOB2.Add(tempImage2);
                            arrayMediaOB2.Add(imageName);

                            if (m_MitsuDoubleFrame)
                                arrayMediaOB2.Add(savingFolder[0] + "\\" + nextFileNoPath);

                            if (m_Display == 2 && savingFolder[1] != null)
                                arrayMediaOB2.Add(savingFolder[1] + "\\" + fName);

                            //Start a new thread to the image Processing
                            if (processFlag)
                            {
                                if (m_IngestedFromFolder)
                                    ImageSaving((object)arrayMediaOB2);
                                else
                                    ThreadPool.QueueUserWorkItem(new WaitCallback(ImageSaving), (object)arrayMediaOB2);
                                //ImageSaving((object)arrayMediaOB2);
                                flagCounter++;
                                if (flagCounter > threadCount)
                                {
                                    processFlag = false;
                                    flagCounter = 1;
                                }
                            }
                            else
                            {
                                checkLogin();
                                ImageSaving((object)arrayMediaOB2);
                                processFlag = true;
                            }
                        }
                    }
                }
                catch (Exception err)
                {
                    MessageBox.Show(err.ToString());
                    status = false;
                    return status;
                }
            }

            try
            {
                Directory.Delete(tempFramePath, true);
            }
            catch (Exception err)
            {
                deleteTmp.Add(tempFramePath);
            }

            status = true;
            pClient.SendMessage("Image processing and saving complete");
            return status;
        }

        /// <summary>
        /// Get the suffix for naming
        /// call by ImageProcess
        /// before image is processing
        /// </summary>
        /// <param name="length"></param>
        /// <param name="suffix"></param>
        private void GetSuffix(int length, out string suffix)
        {
            suffix = "";
            for (int j = 0; j < (6 - length); j++)
                suffix = suffix + '0';
        }


        /// <summary>
        /// Processing the Image Ingesting and save the file
        /// call by ImageProcess
        /// After the overlay image has been appied
        /// </summary>
        /// <param name="ob"></param>
        public void ImageSaving(object ob)
        {
            ArrayList mediaOB = (ArrayList)ob;
            Thread.CurrentThread.Priority = ThreadPriority.Highest;
            int[] sliceIndex = new int[]{1, 0};
            string[] filePath = new string[2];
            ImageIngestion.disPlayError traceIngest = new ImageIngestion.disPlayError(trace);
            ImageIngestion.downQuality downQ = new ImageIngestion.downQuality(downQuality);
            Image localSource = (Image)mediaOB[0];
            mediaOB.RemoveAt(0);

            if(m_IngestedFromFolder)
                LoadImage(localSource.Width, localSource.Height);

            filePath[0] = mediaOB[0].ToString();
            //Start Image Ingestiong
            if (m_Display == 1)
            {
                string nextFramePath = "";

                if (m_MitsuDoubleFrame)
                    nextFramePath = mediaOB[1].ToString();

                m_ImageOb.MitsuResize( nextFramePath ,m_SameSize, localSource, filePath[0], m_Quality, m_Left_STW, m_Left_STH, m_Left_LW, m_Left_LH, m_RectWStart, m_RectHStart, m_RectWidth, m_RectHight, traceIngest, downQ);
            }
            else if (m_Display == 2)
            {
                if (mediaOB.Count > 1)
                {
                    filePath[1] = mediaOB[1].ToString();
                    sliceIndex[1] = 1;
                }
                m_ImageOb.RibbonDivide(localSource, m_Left_STW, m_Left_STH, m_Left_LW, m_Left_LH, m_Right_STW, m_Right_STH, m_Right_LW, m_Right_LH, sliceIndex, filePath, m_RectWStart, m_RectHStart, m_RectWidth, m_RectHight, m_Quality, traceIngest, downQ);
            }
            else
            {
                m_ImageOb.TickerResize(localSource, m_RectHight, sliceIndex, filePath, m_Quality, traceIngest, downQ);
                //imageingestOb.DivideImage(m_TotalSlices, localSource, m_FrameWidth, m_FrameHigth, sliceIndex, filePath, trace);
            }
            localSource.Dispose();
        }

        /// <summary>
        /// Bring down the quality of JPEG file
        /// </summary>
        /// <param name="quality"></param>
        private void downQuality(int quality)
        {
            m_Quality = quality;
        }
    }
}